setfenv(1, require'winapi')
require'winapi.window'
require'winapi.router'
require'winapi.comctl'
require'winapi.combobox'

InitCommonControlsEx(ICC_USEREX_CLASSES)

--creation

ffi.cdef[[
typedef struct tagCOMBOBOXEXITEMW
{
	 UINT mask;
	 INT_PTR iItem;
	 LPWSTR pszText;
	 int cchTextMax;
	 int iImage;
	 int iSelectedImage;
	 int iOverlay;
	 int iIndent;
	 LPARAM lParam;
} COMBOBOXEXITEMW, *PCOMBOBOXEXITEMW;
typedef COMBOBOXEXITEMW const *PCCOMBOEXITEMW;
]]

WC_COMBOBOXEX = "ComboBoxEx32"

CBES_EX_NOEDITIMAGE           = 0x00000001
CBES_EX_NOEDITIMAGEINDENT     = 0x00000002
CBES_EX_PATHWORDBREAKPROC     = 0x00000004
CBES_EX_NOSIZELIMIT           = 0x00000008
CBES_EX_CASESENSITIVE         = 0x00000010

CBEIF_TEXT              = 0x00000001
CBEIF_IMAGE             = 0x00000002
CBEIF_SELECTEDIMAGE     = 0x00000004
CBEIF_OVERLAY           = 0x00000008
CBEIF_INDENT            = 0x00000010
CBEIF_LPARAM            = 0x00000020
CBEIF_DI_SETITEM        = 0x10000000

COMBOBOXEX_DEFAULTS = {
	class = WC_COMBOBOXEX,
	style = bit.bor(WS_CHILD, WS_VISIBLE),
	x = 10, y = 10, w = 100, h = 100,
}

function CreateComboBoxEx(info)
	info = update({}, COMBOBOXEX_DEFAULTS, info)
	return CreateWindow(info)
end

COMBOBOXEXITEM = struct{
	ctype = 'COMBOBOXEXITEMW', mask = 'mask',
	fields = mfields{
		'pos', 'iItem', 0, countfrom0,
		'caption', 'pszText', CBEIF_TEXT, wcs,
		'image', 'iImage', CBEIF_IMAGE, pass,
		'selected_image', 'iSelectedImage', CBEIF_SELECTEDIMAGE, pass,
		'overlay_image', 'iOverlay', CBEIF_OVERLAY, pass,
		'indent', 'iIndent', CBEIF_INDENT, pass,
	}
}

--commands

CBEM_INSERTITEMA         = (WM_USER + 1)
CBEM_SETIMAGELIST        = (WM_USER + 2)
CBEM_GETIMAGELIST        = (WM_USER + 3)
CBEM_GETITEMA            = (WM_USER + 4)
CBEM_SETITEMA            = (WM_USER + 5)
CBEM_DELETEITEM          = CB_DELETESTRING
CBEM_GETCOMBOCONTROL     = (WM_USER + 6)
CBEM_GETEDITCONTROL      = (WM_USER + 7)
CBEM_SETEXSTYLE          = (WM_USER + 8)  -- use  SETEXTENDEDSTYLE instead
CBEM_SETEXTENDEDSTYLE    = (WM_USER + 14) -- lparam == new style, wParam (optional) == mask
CBEM_GETEXSTYLE          = (WM_USER + 9)  -- use GETEXTENDEDSTYLE instead
CBEM_GETEXTENDEDSTYLE    = (WM_USER + 9)
CBEM_SETUNICODEFORMAT    = CCM_SETUNICODEFORMAT
CBEM_GETUNICODEFORMAT    = CCM_GETUNICODEFORMAT
CBEM_SETEXSTYLE          = (WM_USER + 8)
CBEM_GETEXSTYLE          = (WM_USER + 9)
CBEM_HASEDITCHANGED      = (WM_USER + 10)
CBEM_INSERTITEMW         = (WM_USER + 11)
CBEM_SETITEMW            = (WM_USER + 12)
CBEM_GETITEMW            = (WM_USER + 13)

function ComboBoxEx_InsertItem(window, item) --returns index
	item = ffi.cast('PCOMBOBOXEXITEMW', COMBOBOXEXITEM(item))
	return checkpoz(SNDMSG(window, CBEM_INSERTITEMW, 0, item))
end

function ComboBoxEx_DeleteItem(window, pos) --returns count
	return checkpoz(SNDMSG(window, CBEM_DELETEITEM, countfrom0(pos)))
end

--showcase

if not ... then
require'winapi.showcase'
local window = ShowcaseWindow()

local cb = CreateComboBoxEx{parent = window, y = 10, w = 200, style = bit.bor(WS_CHILD, WS_VISIBLE, CBS_DROPDOWNLIST)}
ComboBoxEx_InsertItem(cb, {caption = 'Option #1'})
ComboBoxEx_InsertItem(cb, {caption = 'Option #2'})
ComboBoxEx_InsertItem(cb, {caption = 'Option #3 (2nd option is gone)'})
ComboBoxEx_DeleteItem(cb, 2)

local cb = CreateComboBoxEx{parent = window, y = 40, style = bit.bor(WS_CHILD, WS_VISIBLE, CBS_DROPDOWN)}
ComboBoxEx_InsertItem(cb, {caption = 'Shotgun'})
ComboBoxEx_InsertItem(cb, {caption = 'Gunpowder'})

local cb = CreateComboBoxEx{parent = window, y = 70, w = 200, h = 200, style = bit.bor(WS_CHILD, WS_VISIBLE)}
ComboBoxEx_InsertItem(cb, {caption = 'Hard as a rock'})
ComboBoxEx_InsertItem(cb, {caption = 'Spongy'})

MessageLoop()
end

